import { PropType, computed, defineComponent, onUnmounted, reactive, ref, watchEffect } from "vue";

export interface SplitProps {
    dir?: 'v' | 'h',
    split?: number | string,
    min?: number,
    max?: number,
}

export default defineComponent({
    name: 'Split',
    props: {
        dir: {
            type: String as PropType<SplitProps['dir']>,
            default: 'v'
        },
        split: {
            type: [Number, String] as PropType<SplitProps['split']>,
        },
        min: {
            type: Number,
            default: 40
        },
        max: {
            type: Number,
        }
    },
    setup (props: SplitProps, {slots}) {
        const classList = computed(() => ({
            'cm-split-wrap': true,
            [`cm-split-wrap-${props.dir}`]: true
        }));

        let initSplit: any = props.split;
        if (initSplit && initSplit < 1) {
            initSplit = initSplit * 100 + '%';
        }

        const split = ref(initSplit || '50%');
        const store = reactive({
            dragging: false,
            x: NaN,
            y: NaN,
            deltaX: 0,
            deltaY: 0
        });

        const wrap = ref<HTMLDivElement|null>();
        const prev = ref<HTMLDivElement|null>();
        const handlerClassList = computed(() => ({
            'cm-split-handler': true,
            'cm-split-dragging': store.dragging,
            [`cm-split-handler-${props.dir}`]: !!props.dir
        }));

        if (!slots.prev) {
            console.warn('Split need prev Slot Element');
        }
        if (!slots.next) {
            console.warn('Split need next Slot Element');
        }

        watchEffect(() => {
            const {deltaX, deltaY} = store;
            if (wrap.value) {
                const wrapRect = wrap.value.getBoundingClientRect();
                const wrapSize = props.dir === 'v' ? wrapRect.width : wrapRect.height;
                const wh = props.dir === 'v' ? prev.value.style.width : prev.value.style.height;
                let whVal = 0;
                if (wh.indexOf('px') > -1) {
                    whVal = parseFloat(wh) / wrapSize * 100;
                } else {
                    whVal = parseFloat(wh);
                }
                const max = props.max ? props.max / wrapSize * 100 : 100 - props.min / wrapSize * 100;
                whVal = whVal + (props.dir === 'v' ? deltaX : deltaY)/wrapSize * 100;
                whVal = Math.max(whVal, props.min / wrapSize * 100);
                whVal = Math.min(whVal, max);
                split.value = whVal + '%';
            }
        });

        const prevStyle = computed(() => {
            return {[`${props.dir === 'v' ? 'width' : 'height'}`]: split.value};
        });
        const handlerStyle = computed(() => {
            return {[`${props.dir === 'v' ? 'left' : 'top'}`]: split.value};
        });
        const nextStyle = {
            flex: '1'
        };

        const onDragStart = (e: any) => {
            if (typeof e.button === 'number' && e.button !== 0) return false;

            store.dragging = true;
            const x = e.clientX;
            const y = e.clientY;
            store.x = x;
            store.y = y;

            document.addEventListener('mousemove', onDragMove, false);
            document.addEventListener('mouseup', onDragEnd, false);
        };

        const onDragMove = (e: any) => {
            const deltaX = e.clientX - store.x;
            const deltaY = e.clientY - store.y;
            store.x = e.clientX;
            store.y = e.clientY;
            store.deltaX = deltaX;
            store.deltaY = deltaY;
        };
        const onDragEnd = (e: any) => {
            store.dragging = false;
            document.removeEventListener('mousemove', onDragMove);
            document.removeEventListener('mouseup', onDragEnd);
            store.deltaX = 0;
            store.deltaY = 0;
        };

        onUnmounted(() => {
            document.removeEventListener('mousemove', onDragMove);
            document.removeEventListener('mouseup', onDragEnd);
        });

        const arr = [1,2,3,4,5,6,7,8];
        return () => <div class={classList.value} ref={wrap}>
            <div style={prevStyle.value} ref={prev} class={`cm-split-panel cm-split-${props.dir === 'v' ? 'left' : 'top'}`}>
                {slots.prev?.()}
            </div>
            <div class="cm-slpit-handler-wrap" style={handlerStyle.value}>
                <div class={handlerClassList.value} onMousedown={onDragStart}>
                    <div class="cm-split-handler-bar-wrap">
                        {
                            arr.map(() => {
                                return <div class="cm-split-handler-bar"></div>;
                            })
                        }
                    </div>
                </div>
            </div>
            <div style={nextStyle} class={`cm-split-panel cm-split-${props.dir === 'v' ? 'right' : 'bottom'}`}>
                {slots.next?.()}
            </div>
        </div>;
    }
});
